/**
 * Copyright [2019] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.aspect;

import com.hyts.aspect.advisor.MethodAdvice;
import com.hyts.aspect.anchor.AnchorPoint;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatchers;

import java.util.logging.Logger;

/**
 * @project-name:coffice-toolbox
 * @package-name:com.hyts.aspect
 * @author:LiBo/Alex
 * @create-date:2020-04-26 17:15
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description:
 */
public class AspectProxy {

    private static Logger logger = Logger.getLogger(AspectProxy.class.getName());

    public static <T> T proxy(Class<T> interfaceClazz){
        try {
            return new ByteBuddy()
                    .subclass(interfaceClazz) // 动态生成Service类的子类
                    .method(ElementMatchers.any()) // 拦截所有方法
                    .intercept(Advice.to(MethodAdvice.class)) // 使用MethodAdvice类作为拦截器，Advice是AOP的概念，似乎一般翻译为「通知」？
                    .make() // 作出
                    .load(interfaceClazz.getClassLoader()) // 硬塞给ClassLoader
                    .getLoaded() // 拿到Class对象
                    //.getConstrutor(null ) // Class.newInstance() 在Java 9中被废弃了，是个很有意思的故事，有兴趣可以去了解一下
                    .newInstance();
        } catch (Exception e) {
            logger.severe(e.getMessage());
            return null;
        }
    }


    public static void main(String[] args){
        AspectProxy.proxy(AnchorPoint.class).test();
    }

}
